import sys
import logging
import yaml

from src.py_data_sync.source import MysqlSource, PgsqlSource
from src.py_data_sync.sink import LocalFsSink, S3Sink


logging.basicConfig(level=logging.INFO)


class Context:

    def __init__(self, argv) -> None:
        self.parse_argv(argv)
        self.conf = self.parse_conf(argv[2])
        self.source = self.create_source()
        self.sink = self.create_sink(self.source)

    def parse_argv(self, argv):
        """
        parse the command line argv
        """
        if len(argv) < 3:
            if len(argv) < 2:
                logging.error("command error. try -h to see how to use")
                sys.exit(1)
            if argv[1] == "-h":
                self.help()
            else:
                logging.error("command error. try -h to see how to use")
                sys.exit(1)
        if argv[1] != "-c":
            logging.error("command error. try -h to see how to use")
            sys.exit(1)

    def help(self):
        print("\nUSAGE: python synctool.py -c your_config.yaml\n")
        sys.exit(0)

    def parse_conf(self, filepath):
        """
        parse yaml conf
        """
        try:
            with open(filepath, "r") as f:
                conf = yaml.safe_load(f)
        except Exception as e:
            logging.error("read config yaml file error. please check your file")
            logging.error("exception: %s" % e.__str__())
            sys.exit(1)
        if "source" not in conf or "sink" not in conf:
            logging.error("config yaml file warn, see template.")
            sys.exit(1)
        if conf["source"].get("type") not in ("mysql", "pgsql"):
            logging.error("source.type just support one of [mysql, pgsql]")
            sys.exit(1)
        if conf["sink"].get("type") not in ("local", "s3"):
            logging.error("sink.type just support one of [local, s3]")
            sys.exit(1)

        return conf

    def create_source(self):
        source_conf = self.conf["source"]
        if source_conf["type"] == "mysql":
            return MysqlSource(source_conf)
        else:
            return PgsqlSource(source_conf)

    def create_sink(self, source):
        sink_conf = self.conf["sink"]
        if sink_conf["type"] == "local":
            return LocalFsSink(source, sink_conf)
        else:
            return S3Sink(source, sink_conf)

    def run(self):
        logging.info("running...")
        self.sink.load()
